import os
import django
from openpyxl import load_workbook
from django.db import transaction

# 设置Django环境
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "house_crm.settings")
django.setup()

# 导入你需要导入数据的模型
# 请根据实际情况替换为你的应用和模型
from house.models import MeterReading


def import_excel_to_model(file_path, model, field_mapping=None, start_row=2):
    """
    从Excel导入数据到Django模型

    参数:
    - file_path: Excel文件路径
    - model: 要导入的Django模型类
    - field_mapping: 字段映射字典，键为Excel列名，值为模型字段名
                     如果为None，则尝试使用verbose_name自动匹配
    - start_row: 数据开始的行号（默认为2，因为第1行通常是表头）
    """
    # 加载Excel文件
    wb = load_workbook(file_path)
    ws = wb.active  # 获取活动工作表
    
    # 获取表头
    headers = {}
    for col in range(1, ws.max_column + 1):
        header_value = ws.cell(row=1, column=col).value
        if header_value:
            headers[col] = str(header_value).strip()
    
    # 确定字段映射
    if not field_mapping:
        field_mapping = {}
        model_fields = {
            str(field.verbose_name).strip(): field.name
            for field in model._meta.get_fields()
            if hasattr(field, 'verbose_name')
        }
        
        # 尝试通过verbose_name匹配
        for col, header in headers.items():
            if header in model_fields:
                field_mapping[col] = model_fields[header]
    
    # 验证映射是否有效
    valid_fields = [f.name for f in model._meta.get_fields() if hasattr(f, 'name')]
    for col, field_name in field_mapping.items():
        if field_name not in valid_fields:
            raise ValueError(f"模型 {model.__name__} 中不存在字段 {field_name}")
    
    print(f"找到 {len(field_mapping)} 个匹配的字段，开始导入数据...")
    
    # 导入数据
    success_count = 0
    error_count = 0
    errors = []
    
    # 使用事务确保数据一致性
    with transaction.atomic():
        for row in range(start_row, ws.max_row + 1):
            try:
                # 准备要创建的对象数据
                data = {}
                for col, field_name in field_mapping.items():
                    cell_value = ws.cell(row=row, column=col).value
                    # 根据需要添加类型转换逻辑
                    data[field_name] = cell_value
                
                # 创建模型对象
                model.objects.create(**data)
                success_count += 1
                
                # 每100条记录打印一次进度
                if success_count % 100 == 0:
                    print(f"已导入 {success_count} 条记录...")
            
            except Exception as e:
                error_count += 1
                errors.append(f"行 {row} 导入失败: {str(e)}")
                # 如果希望遇到错误时继续导入，可以注释下面这行
                # raise
    
    print(f"导入完成！成功: {success_count} 条, 失败: {error_count} 条")
    
    # 打印错误信息
    if errors:
        print("\n错误详情:")
        for error in errors[:10]:  # 只显示前10个错误
            print(error)
        if len(errors) > 10:
            print(f"... 还有 {len(errors) - 10} 个错误未显示")
    
    return success_count, error_count


if __name__ == "__main__":
    # 示例用法
    # 替换为你的Excel文件路径和模型
    excel_path = os.path.join(os.path.dirname(__file__), "导入数据.xlsx")
    
    # 字段映射（如果Excel列名与模型verbose_name不匹配时需要手动指定）
    # 格式: {Excel列号: 模型字段名}
    # field_mapping = {
    #     1: 'name',
    #     2: 'email',
    #     3: 'age'
    # }
    
    # 导入数据
    import_excel_to_model(
        file_path=excel_path,
        model=MeterReading,
        # field_mapping=field_mapping,  # 如果需要手动映射则取消注释
        start_row=2
    )
